package devc;
import java_cup.runtime.*;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.HashMap;
import automatagen.*;

parser code {:
	
	public static Lex myLex;
	
	static Integer baseAddress;
	static String  absoluteDir;
	static String  projName;
	
	public static void main(String args[]) throws Exception {
		SymbolFactory sf = new DefaultSymbolFactory();
		projName = args[1];
		baseAddress = Integer.parseInt(args[2]);
		absoluteDir = args[3];
		if (args.length==0){
			myLex = new Lex(System.in,sf);
			new parser(myLex,sf).parse();
		}else{
			myLex = new Lex(new java.io.FileInputStream(args[0]),sf);
			new parser(myLex,sf).parse();
		}
	}
	//public static void addParam
:}

terminal T_OPEN_PAR, T_CLOSE_PAR, T_PONTVIRG, T_DOISPONTOS,T_DEVC,T_OPEN_CHAVE, T_CLOSE_CHAVE, T_IGUAL,
T_ASPAS, T_ASPA,T_PERCENT, T_PERCENT_RESERVED, T_PERCENT_MASK, T_S, T_R,T_DOT;
 terminal String T_MASKREP;
 terminal T_DC_SCML_PORT, T_DC_TLM_PORT, T_DC_CLK_PORT, T_DC_FORMAT, T_DC_SERVICE,T_MAIOR, T_MENOR, T_VIRG, T_READ, T_WRITE,
T_DC_REG, T_DC_BUFFER, T_DC_DRV_MAP, T_DC_OS,T_DC_OS_MAP, T_OPEN, T_INIT, T_RELEASE, T_CLOSE, T_IOCTL,
T_SEEK, T_DEV_CTOR, T_SET_ADDRESS, T_BINDTO, T_SET_ACTION, T_PRE, T_POS, T_WAIT_STATE, T_INTERRUPT,
T_POLLING;
terminal String T_IDENT, T_OPER;
/*terminal T_LETTER, T_DIGIT;*/
terminal String T_INT;
terminal T_PLUS, T_UCLINUX;

non terminal input;
non terminal AutomataGen devc_obj_def, ctor_definition;
non terminal port_definition;
non terminal DataFormat format_definition;
non terminal String fmt_decl,params_fmt,param_fmt,ret_fmt,reg_fmt,bits;
non terminal serv_definition;
non terminal String sto_definition, reg_decl;
non terminal rw,buffer_decl;
non terminal VarMapDefinition varmap_definition;
non terminal HashMap<String,VarMap> varmap_decl;
non terminal VarMap varmap;
non terminal HashMap<String,String> semivar;
non terminal os_definiton,os_type,osmap_definition,osimap_decl,posix_intf;
non terminal MethodDefinition method_definition;
non terminal RegisterMap address_def;
non terminal bind_def;
non terminal Automata action_def;
non terminal ServiceType attrib;
non terminal ArrayList<Tripla> expr;
non terminal Tripla l_expr,assign, cond;
non terminal sinc_decl,wait_decl,intr_decl,poll_decl;

   /*%union {
     int       t_int;  /* For the lexical analyser. NUMBER tokens 
     char      ident;  /* For the lexical analyser. IDENT tokens 
   }*/
/*%type <t_int>   T_INT
%type <ident> T_IDENT
%type <t_int> address_def*/

/*%start nt_devc_spec*/

input ::= T_DEVC T_OPEN_PAR T_IDENT T_CLOSE_PAR T_OPEN_CHAVE devc_obj_def:def1 T_CLOSE_CHAVE
{:
	def1.generateAutomatasCode();
:};

devc_obj_def ::= port_definition T_PONTVIRG devc_obj_def:def_aut {: RESULT = def_aut; :}
| format_definition:format T_PONTVIRG devc_obj_def:def_aut {: def_aut.addFormat(format); RESULT = def_aut; :}
| serv_definition T_PONTVIRG devc_obj_def:def_aut {: RESULT = def_aut; :}
| sto_definition:sto T_PONTVIRG devc_obj_def:def_aut {: def_aut.addFormatMapReg(sto); RESULT = def_aut; :}
| varmap_definition:vardef devc_obj_def:def_aut {: def_aut.addVarMapDefinition(vardef); RESULT = def_aut; :}
| os_definiton T_PONTVIRG devc_obj_def:def_aut {: RESULT = def_aut; :}
| osmap_definition devc_obj_def:def_aut {: RESULT = def_aut; :}
| ctor_definition:ctor1 {: RESULT = ctor1; :};

port_definition ::= T_DC_SCML_PORT T_IDENT /*{printf("-TESTE %s|%d-\n", current[pos-1-0],pos);pos=0;}*/
| T_DC_TLM_PORT T_IDENT
| T_DC_CLK_PORT T_IDENT;

format_definition ::= T_DC_FORMAT T_IDENT:name T_IGUAL fmt_decl:format {: DataFormat dt = new DataFormat(name,format); RESULT = dt; :};

fmt_decl ::= params_fmt:params {: RESULT = params; :}
| ret_fmt:ret {: RESULT = ret; :};

params_fmt ::= T_ASPAS param_fmt:param T_ASPAS {: RESULT = param; :};

param_fmt ::= T_PERCENT T_IDENT:ident T_DOISPONTOS T_INT:inte T_DOISPONTOS T_S param_fmt:param {: RESULT = "%" + ident + ":" + inte + ":s" + param; :}
| T_PERCENT T_IDENT:ident T_DOISPONTOS T_INT:inte param_fmt:param {: RESULT = "%" + ident + ":" + inte + param; :}
| T_PERCENT_RESERVED T_DOISPONTOS T_INT:inte param_fmt:param {: RESULT = "%RESERVED:" + inte + param; :}
| reg_fmt:reg param_fmt:param {: RESULT = reg + param; :}
| T_PERCENT T_IDENT:ident T_DOISPONTOS T_INT:inte T_DOISPONTOS T_S {: RESULT = "%" + ident + ":" + inte + ":s"; :}
| T_PERCENT T_IDENT:ident T_DOISPONTOS T_INT:inte {: RESULT = "%" + ident + ":" + inte; :}
| T_PERCENT_RESERVED T_DOISPONTOS T_INT:inte {: RESULT = "%RESERVED:" + inte; :}
| reg_fmt:reg {: RESULT = reg; :};

ret_fmt ::= T_ASPAS T_PERCENT T_DOISPONTOS T_R T_ASPAS {: RESULT = "%:r"; :}
| T_ASPAS T_PERCENT T_DOISPONTOS T_R T_DOISPONTOS T_S T_ASPAS {: RESULT = "%:r:s"; :};

reg_fmt ::= T_PERCENT T_IDENT:ident T_DOISPONTOS T_INT:inte T_PERCENT_MASK T_DOISPONTOS T_ASPA bits:mascara T_ASPA {: RESULT = "%" + ident + ":" + inte + "%MASK:" + mascara; :};

bits ::= T_MASKREP:masc bits:masc_c {: RESULT = masc + masc_c; :}
| T_DOT bits:masc_c {: RESULT = "." + masc_c; :}
| T_MASKREP:masc {: RESULT = masc; :}
| T_DOT {: RESULT = "."; :};

serv_definition ::= T_DC_SERVICE T_MENOR T_IDENT T_MAIOR T_IDENT
| T_DC_SERVICE T_MENOR T_IDENT T_VIRG rw T_MAIOR T_IDENT;

sto_definition ::= reg_decl:reg {: RESULT = reg; :}
| buffer_decl {: RESULT = ""; :}; 

reg_decl ::= T_DC_REG T_MENOR T_IDENT:format T_MAIOR T_IDENT:ident {: RESULT = ident + ":" + format; :}
| T_DC_REG T_MENOR T_IDENT:format T_VIRG rw T_MAIOR T_IDENT:ident {: RESULT = ident + ":" + format; :}; 

rw ::= T_READ
| T_WRITE;

buffer_decl ::= T_DC_BUFFER T_IDENT T_DOISPONTOS T_INT T_DOISPONTOS T_INT;

varmap_definition ::= T_DC_DRV_MAP T_IDENT:name T_OPEN_CHAVE varmap_decl:varmaps T_CLOSE_CHAVE {: VarMapDefinition vardef = new VarMapDefinition(name,varmaps); RESULT  = vardef;:};

varmap_decl ::= varmap:map T_PONTVIRG {: HashMap<String,VarMap> varmaps = new HashMap<String,VarMap>(); varmaps.put(map.getName(),map); RESULT = varmaps; :}
| varmap:map T_PONTVIRG varmap_decl:varmaps {: varmaps.put(map.getName(),map); RESULT = varmaps; :};

varmap ::= T_IDENT:name T_IGUAL semivar:vars {: VarMap varmap = new VarMap(name,vars); RESULT = varmap; :};

semivar ::= T_IDENT:ident {: HashMap<String,String> name = new HashMap<String,String>(); name.put(ident,ident); RESULT = name;  :}
| T_IDENT:ident1 T_DOT T_IDENT:ident2 {: HashMap<String,String> name = new HashMap<String,String>(); name.put(ident2,ident1); RESULT = name; :}
| T_IDENT:ident T_PLUS semivar:name {: name.put(ident,ident); RESULT = name; :}
| T_IDENT:ident1 T_DOT T_IDENT:ident2 T_PLUS semivar:name {: name.put(ident2,ident1); RESULT = name; :};

os_definiton ::= T_DC_OS T_MENOR os_type T_MAIOR T_IDENT;

os_type ::= T_UCLINUX;

osmap_definition ::= T_DC_OS_MAP T_IDENT T_OPEN_CHAVE osimap_decl T_CLOSE_CHAVE;

osimap_decl ::= T_IDENT T_DOT posix_intf T_IGUAL T_IDENT T_PONTVIRG osimap_decl
| T_IDENT T_DOT posix_intf T_IGUAL T_IDENT T_PONTVIRG;

posix_intf ::= T_OPEN
| T_INIT
| T_WRITE
| T_READ
| T_RELEASE
| T_CLOSE
| T_IOCTL
| T_SEEK;

ctor_definition ::= T_DEV_CTOR T_OPEN_PAR T_IDENT T_CLOSE_PAR T_OPEN_CHAVE method_definition:md1 T_CLOSE_CHAVE
{:
	RESULT = new AutomataGen(md1, parser.projName, parser.baseAddress, parser.absoluteDir);	
:};

method_definition ::= address_def:addr T_PONTVIRG method_definition:met {: met.addRegister(addr); RESULT = met;:}
| action_def:ad1 method_definition:met
{:
   if (met.getAutomatas().containsKey(ad1.getName())){
       met.getAutomatas().get(ad1.getService()).addTriplas(ad1.getType(),ad1.getTripla());
     }else{
       met.addAutomata(ad1);
     }
   RESULT = met;
 :}
| bind_def T_PONTVIRG method_definition:met {: RESULT = met;:}
| address_def:addr T_PONTVIRG {: MethodDefinition metDef = new MethodDefinition(); metDef.addRegister(addr); RESULT = metDef;:}
| action_def:ad1 
{:
  MethodDefinition metDef = new MethodDefinition();
  metDef.addAutomata(ad1);
  RESULT = metDef;
:}
| bind_def T_PONTVIRG {: RESULT = new MethodDefinition();:};

address_def ::= T_IDENT:name T_DOT T_SET_ADDRESS T_OPEN_PAR T_INT:addrs T_CLOSE_PAR {: RESULT = new RegisterMap(name,new Integer(addrs));:};

bind_def ::= T_IDENT T_DOT T_BINDTO T_OPEN_PAR T_IDENT T_CLOSE_PAR
| T_IDENT T_DOT T_BINDTO T_OPEN_PAR T_IDENT T_DOT T_IDENT T_CLOSE_PAR
|T_IDENT T_DOT T_BINDTO T_OPEN_PAR T_IDENT T_DOT T_IDENT T_DOT T_IDENT T_CLOSE_PAR;

action_def ::= T_IDENT:i1 T_DOT T_SET_ACTION T_OPEN_PAR attrib:a1 T_CLOSE_PAR T_OPEN_CHAVE expr:l1 T_CLOSE_CHAVE
{:
RESULT = new Automata(i1,a1,l1);
:}
| T_IDENT:i1 T_DOT T_SET_ACTION T_OPEN_PAR T_CLOSE_PAR T_OPEN_CHAVE expr:l1 T_CLOSE_CHAVE
{:
RESULT = new Automata(i1,ServiceType.NULL,l1);
:};

attrib ::= T_PRE {:RESULT = ServiceType.PRE;:}
| T_POS {:RESULT = ServiceType.POS;:};

expr ::= l_expr:c1 {:ArrayList<Tripla> atripla_c = new ArrayList<Tripla>(); atripla_c.add(c1); RESULT = atripla_c;:}
| assign:a1 T_PONTVIRG {:ArrayList<Tripla> atripla_a = new ArrayList<Tripla>(); atripla_a.add(a1); RESULT = atripla_a;:}
| sinc_decl T_PONTVIRG {:RESULT = new ArrayList();:}
| l_expr:c1 expr:e1 {:e1.add(c1);RESULT=e1;:}
| assign:a1 T_PONTVIRG expr:e1{:e1.add(a1);RESULT=e1;:}
| sinc_decl T_PONTVIRG expr {:RESULT = new ArrayList();:};

l_expr ::= cond:c1 T_OPEN_CHAVE expr:e1 T_CLOSE_CHAVE {:c1.setTriplas(e1);RESULT = c1;:};

/*l_expr : T_IDENT T_OPER T_INT T_PONTVIRG
| T_IDENT T_DOT T_IDENT T_OPER T_INT T_PONTVIRG
| T_IDENT T_OPER T_INT T_OPEN_CHAVE expr T_CLOSE_CHAVE
| T_IDENT T_DOT T_IDENT T_OPER T_INT T_OPEN_CHAVE expr T_CLOSE_CHAVE;*/

assign ::= T_IDENT:i1 T_IGUAL T_INT:int1 {: RESULT = new Tripla(i1,int1); :}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_IGUAL T_INT:int1 {: RESULT = new Tripla(i1.concat(".").concat(i2),int1); :}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_DOT T_IDENT:i3 T_IGUAL T_INT:int1
{:
RESULT = new Tripla(i1.concat(".").concat(i2).concat(".").concat(i3),int1);
:};

sinc_decl ::= wait_decl
| intr_decl
| poll_decl;

wait_decl ::= T_WAIT_STATE T_OPEN_PAR cond T_CLOSE_PAR ;

intr_decl ::= T_INTERRUPT T_OPEN_PAR cond T_CLOSE_PAR;

poll_decl ::= T_POLLING T_OPEN_PAR cond T_CLOSE_PAR;

cond ::= T_IDENT:i1 T_OPER:o1 T_INT:in1 {:RESULT = new Tripla(i1,o1,in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_OPER:o1 T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2),o1,in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_DOT T_IDENT:i3 T_OPER:o1 T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2).concat(".").concat(i3),o1,in1);:}
| T_IDENT:i1 T_MAIOR T_INT:in1  {:RESULT = new Tripla(i1,">",in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_MAIOR T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2),">",in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_DOT T_IDENT:i3 T_MAIOR T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2).concat(".").concat(i3),">",in1);:}
| T_IDENT:i1 T_MENOR T_INT:in1  {:RESULT = new Tripla(i1,"<",in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_MENOR T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2),"<",in1);:}
| T_IDENT:i1 T_DOT T_IDENT:i2 T_DOT T_IDENT:i3 T_MENOR T_INT:in1 {:RESULT = new Tripla(i1.concat(".").concat(i2).concat(".").concat(i3),"<",in1);:}
| /*empty*/;

/*cnoum : article noum {printf("cnoum2 %s %s",$1,$2);} | noum {$$ = "cnoum1";};*/
